#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QTimer>
#include <QScrollBar>
#include <QMessageBox>
#include <QProcess>
#include <QShortcut>
#include <QPluginLoader>
#include <QTranslator>
#include <QLocalSocket>
#include <QLabel>
#include <QLineEdit>
#include <QAbstractItemModel>
#include "aboutdialog.h"
#include "pioplugin.h"
#include "importdialog.h"
#include "importprocess.h"
#include "mediaitemimpl.h"

MainWindow::MainWindow(QSplashScreen * splash, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_core(this)
{
    connect(&m_singleinstance, SIGNAL(newConnection()), SLOT(onNewConnection()));
    m_singleinstance.listen("pio-socket");

    // setup ui
    ui->setupUi(this);
    setWindowIcon(QIcon(":/images/icon.png"));

    // provide the thumbnail database to the collection view
    ui->collectionview->setIconCache(m_core.cache());
    ui->collectionview->setCore(&m_core);
    ui->imageview->setCore(&m_core);

    // setup context menu
    m_contextMenu.addAction(ui->actionEdit);
    m_contextMenu.addAction(ui->actionDevelop);
    m_contextMenu.addSeparator();
    m_contextMenu.addAction(ui->actionDelete);

    m_collectionsContextMenu.addAction(ui->actionNewFolder);
    m_collectionsContextMenu.addAction(ui->actionDeleteFolder);

    ui->menuWindows->addAction(ui->mainToolBar->toggleViewAction());
    ui->menuWindows->addAction(ui->dockWidget->toggleViewAction());

    // create shortcuts
    connect(new QShortcut(Qt::Key_Delete, this), SIGNAL(activated()), SLOT(on_actionDelete_triggered()));
    connect(new QShortcut(Qt::Key_F11, this), SIGNAL(activated()), ui->actionFullscreen, SLOT(trigger()));

    connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(close()));
    connect(ui->actionSmall, SIGNAL(triggered()), ui->collectionview, SLOT(small_thumbnails()));
    connect(ui->actionMedium, SIGNAL(triggered()), ui->collectionview, SLOT(medium_thumbnails()));
    connect(ui->actionLarge, SIGNAL(triggered()), ui->collectionview, SLOT(large_thumbnails()));

    connect(ui->collectionsList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(selectCollections()));
    connect(ui->collectionsList, SIGNAL(dropped(QList<QUrl>,QListWidgetItem*)), this, SLOT(onItemsDroppedOnCollection(QList<QUrl>,QListWidgetItem*)));
    ui->collectionsList->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->collectionsList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCollectionsListContextMenuRequested(QPoint)));

    connect(&m_core, SIGNAL(shown(MediaItemPtr)), ui->collectionview, SLOT(onAdd(MediaItemPtr)), Qt::QueuedConnection);
    connect(&m_core, SIGNAL(hidden(MediaItemPtr)), ui->collectionview, SLOT(onRemove(MediaItemPtr)), Qt::QueuedConnection);
    connect(&m_core, SIGNAL(updated(MediaItemPtr)), ui->collectionview, SLOT(onUpdate(MediaItemPtr)), Qt::QueuedConnection);

    connect(m_core.database(), SIGNAL(keywordsChanged()), this, SLOT(onKeywordsChanged()), Qt::QueuedConnection);

    connect(&m_scanner, SIGNAL(add(MediaItemPtr)), m_core.database(), SLOT(add(MediaItemPtr)), Qt::QueuedConnection);
    connect(&m_scanner, SIGNAL(remove(MediaItemPtr)), m_core.database(), SLOT(remove(MediaItemPtr)), Qt::QueuedConnection);
    connect(&m_scanner, SIGNAL(update(MediaItemPtr,MediaItemImpl::Metadata)), m_core.database(), SLOT(update(MediaItemPtr,MediaItemImpl::Metadata)), Qt::QueuedConnection);

    connect(ui->scrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), ui->collectionview, SLOT(onSetVerticalPosition(int)));

    connect(ui->collectionview, SIGNAL(setVerticalPosition(int)), ui->scrollArea->verticalScrollBar(), SLOT(setValue(int)));
    connect(ui->collectionview, SIGNAL(makeVisible(QRect)), ui->scrollArea, SLOT(onMakeVisible(QRect)));
    connect(ui->collectionview, SIGNAL(contextMenuRequested()), this, SLOT(onContextMenuRequested()));
    connect(ui->collectionview, SIGNAL(view(MediaItemPtr)), this, SLOT(onView(MediaItemPtr)));
    connect(ui->collectionview, SIGNAL(fullscreen(bool)), ui->actionFullscreen, SLOT(setChecked(bool)));
    connect(ui->collectionview, SIGNAL(status(QString)), this, SLOT(setStatus(QString)));

    connect(&m_core, SIGNAL(selectionChanged(QList<MediaItemPtr>)), this, SLOT(onSelectionChanged(QList<MediaItemPtr>)));

    connect(ui->imageview, SIGNAL(closeImage()), this, SLOT(onCloseView()));
    connect(ui->imageview, SIGNAL(prev()), ui->collectionview, SLOT(left()));
    connect(ui->imageview, SIGNAL(next()), ui->collectionview, SLOT(right()));

    connect(&m_slideShowTimer, SIGNAL(timeout()), this, SLOT(onSlideShowTimer()));

    connect(&m_scanner, SIGNAL(status(QString)), this, SLOT(setStatus(QString)));
    connect(m_core.database(), SIGNAL(collectionsChanged()), this, SLOT(onCollectionsChanged()));
    connect(m_core.database(), SIGNAL(keywordsChanged()), this, SLOT(onKeywordsChanged()));

    QActionGroup * previewSizeGroup = new QActionGroup(this);
    previewSizeGroup->addAction(ui->actionSmall);
    previewSizeGroup->addAction(ui->actionMedium);
    previewSizeGroup->addAction(ui->actionLarge);

    QActionGroup * rawFilterGroup = new QActionGroup(this);
    rawFilterGroup->addAction(ui->actionRawAndProcessed);
    rawFilterGroup->addAction(ui->actionRawOnly);
    rawFilterGroup->addAction(ui->actionProcessedOnly);
    rawFilterGroup->addAction(ui->actionUnprocessedRaw);
    rawFilterGroup->addAction(ui->actionNoDevelopedRaw);

    ui->importWidget->hide();

    splash->showMessage(tr("loading plugins..."), Qt::AlignLeft | Qt::AlignBottom, Qt::white);
    loadPlugins();

    m_core.filters()->setExcludedCollections(m_core.settings().value("excludedFolders").toStringList().toSet());

    splash->showMessage(tr("loading library..."), Qt::AlignLeft | Qt::AlignBottom, Qt::white);
#if defined(QT_NO_DEBUG)
    m_core.database()->load(QDir::homePath() + "/.pio/library.xml");
#else
    m_core.database()->load(QDir::homePath() + "/.pio/library-debug.xml");
#endif
    splash->showMessage(tr("updating library..."), Qt::AlignLeft | Qt::AlignBottom, Qt::white);
    m_scanner.scan(m_core.database(), m_core.libraryPath());
    //setFolders(m_core.library()->folders(), false);
    //on_resetCollectionSelection_pressed();

    if(m_core.settings().value("maximized").toBool())
        showMaximized();
    if(m_core.settings().value("thumbnailsize") == "small")
        ui->actionSmall->trigger();
    else if(m_core.settings().value("thumbnailsize") == "large")
        ui->actionLarge->trigger();
    else
        ui->actionMedium->trigger();

    if(m_core.settings().value("rawfilter") ==  "all")
        ui->actionRawAndProcessed->trigger();
    else if(m_core.settings().value("rawfilter") == "raw-only")
        ui->actionRawOnly->trigger();
    else if(m_core.settings().value("rawfilter") == "no-raw")
        ui->actionProcessedOnly->trigger();
    else if(m_core.settings().value("rawfilter") == "undeveloped-raw")
        ui->actionUnprocessedRaw->trigger();
    else if(m_core.settings().value("rawfilter") == "no-developed-raw")
        ui->actionNoDevelopedRaw->trigger();
    else
        ui->actionRawAndProcessed->trigger();

    //onSelectionChanged(ui->collectionview->selection());
    ui->collectionview->setFocus();

    splash->finish(this);
    show();

    processArguments(qApp->arguments());
    //processArguments(QStringList() << "" << "--import" << "/media/EOS_DIGITAL");

    //QLabel * label = new QLabel("some text, blah");
    //label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    //addOverlay(label);
}

MainWindow::~MainWindow()
{
    foreach(PioPlugin * plugin, m_plugins)
        delete plugin;
    if(ui->actionSmall->isChecked())
        m_core.settings().setValue("thumbnailsize", "small");
    else if(ui->actionMedium->isChecked())
        m_core.settings().setValue("thumbnailsize", "medium");
    else if(ui->actionLarge->isChecked())
        m_core.settings().setValue("thumbnailsize", "large");

    if(ui->actionRawAndProcessed->isChecked())
        m_core.settings().setValue("rawfilter", "all");
    else if(ui->actionRawOnly->isChecked())
        m_core.settings().setValue("rawfilter", "raw-only");
    else if(ui->actionProcessedOnly->isChecked())
        m_core.settings().setValue("rawfilter", "no-raw");
    else if(ui->actionUnprocessedRaw->isChecked())
        m_core.settings().setValue("rawfilter", "undeveloped-raw");
    else if(ui->actionNoDevelopedRaw->isChecked())
        m_core.settings().setValue("rawfilter", "no-developed-raw");

    m_core.settings().setValue("fullscreen", isFullScreen());
    m_core.settings().setValue("maximized", isMaximized());

    QDir().mkpath(QDir::homePath() + "/.pio");
#if defined(QT_NO_DEBUG)
    m_core.database()->save(QDir::homePath() + "/.pio/library.xml");
#else
    m_core.database()->save(QDir::homePath() + "/.pio/library-debug.xml");
#endif
    delete ui;
}

QToolBar * MainWindow::toolbar()
{
    return ui->mainToolBar;
}

void MainWindow::setStatus(const QString &str)
{
    statusBar()->showMessage(str);
}

void MainWindow::setFullscreen(bool fullscreen)
{
    if(fullscreen && !isFullScreen()) {
        m_menubarVisible = ui->menuBar->isVisible();
        m_toolbarVisible = ui->mainToolBar->isVisible();
        m_sidebarVisible = ui->dockWidget->isVisible();
        m_statusbarVisible = ui->statusBar->isVisible();
        m_maximized = isMaximized();

        ui->menuBar->hide();
        ui->mainToolBar->hide();
        ui->dockWidget->hide();
        ui->statusBar->hide();
        //connect(ui->stackedWidget, SIGNAL(showMenus(bool)), ui->mainToolBar, SLOT(setVisible(bool)));
        showFullScreen();
    }
    else if(!fullscreen && isFullScreen()) {
        ui->menuBar->setVisible(m_menubarVisible);
        ui->mainToolBar->setVisible(m_toolbarVisible);
        ui->dockWidget->setVisible(m_sidebarVisible);
        ui->statusBar->setVisible(m_statusbarVisible);
        //disconnect(ui->stackedWidget, SIGNAL(showMenus(bool)), ui->mainToolBar, SLOT(setVisible(bool)));
        showNormal();
        if(m_maximized)
            showMaximized();
    }
}

void MainWindow::selectCollections()
{
    QSet<QString> collections = m_core.filters()->excludedCollections();
    for(int i=0; i<ui->collectionsList->count(); i++) {
        QListWidgetItem * item = ui->collectionsList->item(i);
        QString str = (i==0) ? "" : item->text();
        if(item->checkState() == Qt::Unchecked)
            collections.insert(str);
        else
            collections.remove(str);
    }
    m_core.filters()->setExcludedCollections(collections);
}

void MainWindow::onItemsDroppedOnCollection(const QList<QUrl> & urls, QListWidgetItem * item)
{
    int index = 0;
    for(int i=0; i<ui->collectionsList->count(); i++)
        if(ui->collectionsList->item(i)==item)
            index = i;
    QString target;
    if(index != 0)
        target = item->text();
    foreach(QUrl url, urls) {
        MediaItemPtr item = m_core.database()->item(url.toLocalFile());
        if(!item.isNull())
            m_core.moveToCollection(item, target);
    }
}

void MainWindow::onContextMenuRequested()
{
    m_contextMenu.popup(QCursor::pos());
}

void MainWindow::onView(MediaItemPtr item)
{
    ui->stackedWidget->setCurrentIndex(1);
    ui->imageview->load(item);
    ui->imageview->setFocus();
}

void MainWindow::onSelectionChanged(QList<MediaItemPtr> selection)
{
    ui->actionDelete->setEnabled(!selection.empty());
    ui->actionEdit->setEnabled(!selection.empty());
    bool raw = false;
    foreach(MediaItemPtr mi, selection) {
        if(mi->metadata().isRaw) {
            raw = true;
            break;
        }
    }
    if(selection.size() == 0)
        statusBar()->showMessage(QString(tr("%1 item(s)")).arg(m_core.view().size()));
    else if(selection.size() == 1) {
        MediaItemPtr item = *selection.begin();
        statusBar()->showMessage(item->metadata().filename);
        if(ui->stackedWidget->currentIndex() == 1)
            ui->imageview->load(item);
    }
    else
        statusBar()->showMessage(QString(tr("%1 items selected")).arg(m_core.view().size()));
    ui->actionDevelop->setEnabled(raw);
}

void MainWindow::onCloseView()
{
    ui->stackedWidget->setCurrentIndex(0);
    ui->imageview->clear();
    m_slideShowTimer.stop();
    if(isFullScreen())
        setFullscreen(false);
}

void MainWindow::on_checkAllCollectionsButton_pressed()
{
    for(int i=0; i<ui->collectionsList->count(); i++) {
        QListWidgetItem * item = ui->collectionsList->item(i);
        item->setCheckState(Qt::Checked);
    }
    selectCollections();
}

void MainWindow::on_checkNoCollectionsButton_pressed()
{
    for(int i=0; i<ui->collectionsList->count(); i++) {
        QListWidgetItem * item = ui->collectionsList->item(i);
        item->setCheckState(Qt::Unchecked);
    }
    selectCollections();
}

void MainWindow::on_addCollection_pressed()
{
    QDialog d(this);
    QLineEdit e(&d);
    QPushButton b(tr("Ok"), &d);
    b.setAutoDefault(true);
    QBoxLayout l(QBoxLayout::LeftToRight, &d);
    l.addWidget(&e);
    l.addWidget(&b);
    connect(&b, SIGNAL(pressed()), &d, SLOT(accept()));
    if(d.exec() == QDialog::Accepted) {
        QDir dir(m_core.libraryPath());
        dir.mkdir(e.text());
        m_scanner.scan(m_core.database(), m_core.libraryPath());
    }
}

void MainWindow::on_collectionsList_itemDoubleClicked(QListWidgetItem* item)
{
    for(int i=0; i<ui->collectionsList->count(); i++) {
        QListWidgetItem * it = ui->collectionsList->item(i);
        it->setCheckState(it == item ? Qt::Checked : Qt::Unchecked);
    }
    selectCollections();
}

void MainWindow::on_actionDelete_triggered()
{
    QList<MediaItemPtr> items = m_core.selection();
    QString text = QString("Do you want to move %1 file(s) to trash?").arg(items.size());
    if(QMessageBox::question(this, "Move to trash?", text, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) != QMessageBox::Yes)
        return;
    foreach(MediaItemPtr item, items)
        m_core.trash(item);
}

void MainWindow::on_actionEdit_triggered()
{
    QList<MediaItemPtr> items = m_core.selection();

    // @todo reverse list...
    if(items.empty())
        return;
    QStringList files;
    foreach(MediaItemPtr item, items)
        files << item->metadata().filename;
    QProcess::startDetached("gimp \"" + files.join("\" \"") + "\"");
}

void MainWindow::on_actionDevelop_triggered()
{
    QList<MediaItemPtr> items = m_core.selection();
    // @todo reverse list...
    QStringList files;
    foreach(MediaItemPtr item, items)
        if(item->metadata().isRaw)
            files << item->metadata().filename;
    if(!files.isEmpty())
        QProcess::startDetached("ufraw \"" + files.join("\" \"") + "\"");
}

void MainWindow::on_resetCollectionSelection_pressed()
{
    m_core.filters()->setExcludedCollections(m_core.settings().value("excludedFolders").toStringList().toSet());
    onCollectionsChanged();
}

void MainWindow::onNewConnection()
{
    QLocalSocket * sock = m_singleinstance.nextPendingConnection();
    if(sock == 0)
        return;
    sock->waitForDisconnected(2000);
    QString str = sock->readAll();
    sock->close();
    delete sock;

    activateWindow();

    QStringList args = str.split('|');
    processArguments(args);
}

void MainWindow::loadPlugins()
{
    QDir pluginsDir = QDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");

    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QString module = pluginsDir.absoluteFilePath(fileName);
        QPluginLoader loader(module);
        PioPlugin * plugin = qobject_cast<PioPlugin*>(loader.instance());
        if(plugin) {
            plugin->setup(&m_core);
            m_plugins.append(plugin);
            qDebug() << "plugin" << module << "loaded";
        }
        else {
            qDebug() << "could not load plugin" << module << ":" << loader.errorString();
        }
    }
}

void MainWindow::on_actionSave_collection_selection_triggered()
{
    QStringList unchecked;
    for(int i=0; i<ui->collectionsList->count(); i++) {
        QListWidgetItem * item = ui->collectionsList->item(i);
        QString str = (i==0) ? "" : item->text();
        if(item->checkState() == Qt::Unchecked)
            unchecked << str;
    }
    m_core.settings().setValue("excludedFolders", unchecked);
}

void MainWindow::processArguments(QStringList args)
{
    for(int i=1; i<args.size(); i++) {
        if(args[i] == "--import" && i < args.size()) {
            QString source = args[++i];
            QUrl url(source);
            if(url.scheme().isEmpty())
                url = QUrl::fromLocalFile(source);
            m_core.import(url);
        }
        else {
            QMessageBox::information(this, tr("Invalid Argument"), tr("Argument not recognized: ") + args[i]);
        }
    }
}

QTreeWidgetItem * MainWindow::addKeyword(const QString &str, QTreeWidgetItem *parent)
{
    if(parent == NULL) {
        for(int i = 0; i < ui->keywords->topLevelItemCount(); i++) {
            QTreeWidgetItem * item = ui->keywords->topLevelItem(i);
            if(item->text(0) == str)
                return item;
        }
        return new QTreeWidgetItem(ui->keywords, QStringList() << str);
    }
    else {
        for(int i = 0; i < parent->childCount(); i++) {
            QTreeWidgetItem * item = parent->child(i);
            if(item->text(0) == str)
                return item;
        }
        return new QTreeWidgetItem(parent, QStringList() << str);
    }
}

/*void MainWindow::synchronize(const QList<QSharedPointer<Keyword> > &keywords, const QSharedPointer<Keyword> &parent_keyword, QTreeWidgetItem *parent_item)
{
    // get children of given parent item (or top level items if parent_item is NULL)
    QList<QTreeWidgetItem*> items;
    if(parent_item == NULL) {
        for(int i = 0; i < ui->keywords->topLevelItemCount(); i++)
            items.append(ui->keywords->topLevelItem(i));
    }
    else {
        for(int i = 0; i < parent_item->childCount(); i++)
            items.append(parent_item->child(i));
    }

    // get keywords at this level as set
    QSet<QString> set;
    foreach(QSharedPointer<Keyword> kw, keywords) {
        if(kw->parent() == parent_keyword)
            set.insert(kw->keyword());
    }

    // remove obsolete items
    foreach(QTreeWidgetItem * item, items) {
        if(set.contains(item->text(0))) {
            set.remove(item->text(0));
        }
        else {
            if(parent_item == NULL) {
                int i = ui->keywords->indexOfTopLevelItem(item);
                QTreeWidgetItem * tmp = ui->keywords->takeTopLevelItem(i);
                if(tmp)
                    delete tmp;
            }
            else {
                int i = parent_item->indexOfChild(item);
                QTreeWidgetItem * tmp = parent_item->takeChild(i);
                if(tmp)
                    delete tmp;
            }
        }
    }

    // add new children
    foreach(QString k, set) {
        QTreeWidgetItem * item = new QTreeWidgetItem(QStringList() << k);
        if(parent_item == NULL)
            ui->keywords->addTopLevelItem(item);
        else
            parent_item->addChild(item);
    }
}*/

void MainWindow::on_actionRawAndProcessed_triggered()
{
    m_core.filters()->setRawType(PioCore::RawAndOther);
}

void MainWindow::on_actionRawOnly_triggered()
{
    m_core.filters()->setRawType(PioCore::Raw);
}

void MainWindow::on_actionProcessedOnly_triggered()
{
    m_core.filters()->setRawType(PioCore::Other);
}

void MainWindow::import(ImportModule * module, QList<int> selection, bool deleteSource, bool ejectMedium)
{
    ImportProcess * import = new ImportProcess(&m_core, module, selection, deleteSource, ejectMedium, this);
    connect(ui->importCancelButton, SIGNAL(pressed()), import, SLOT(stop()));
    connect(import, SIGNAL(progress(int)), ui->importProgressBar, SLOT(setValue(int)));
    connect(import, SIGNAL(finished()), ui->importWidget, SLOT(hide()));
    connect(import, SIGNAL(finished()), import, SLOT(deleteLater()));
    ui->importProgressBar->setRange(0, selection.size());
    ui->importProgressBar->setFormat(tr("%v of %m files completed..."));
    ui->importWidget->show();
    import->start();
}

void MainWindow::on_actionUnprocessedRaw_triggered()
{
    m_core.filters()->setRawType(PioCore::UnprocessedRaw);
}

void MainWindow::on_actionSlideShow_triggered()
{
    m_slideShow = m_core.selection();
    if(m_slideShow.isEmpty())
        return;

    ui->stackedWidget->setCurrentIndex(1);
    ui->imageview->setFocus();
    setFullscreen(true);
    onSlideShowTimer();
    m_slideShowTimer.setInterval(6000);
    m_slideShowTimer.start();
}

void MainWindow::onSlideShowTimer()
{
    if(m_slideShow.isEmpty())
        return;
    MediaItemPtr item = m_slideShow[0];
    m_slideShow.removeAt(0);
    m_slideShow.append(item);
    ui->imageview->load(item);
}

void MainWindow::on_actionNoDevelopedRaw_triggered()
{
    m_core.filters()->setRawType(PioCore::UnprocessedRawAndOther);
}

void MainWindow::on_actionUpdateLibrary_triggered()
{
    m_scanner.scan(m_core.database(), m_core.libraryPath());
    //setFolders(m_core.library()->folders(), true);
}

void MainWindow::on_actionAbout_triggered()
{
    QStringList infos;

    //infos << "<p>\xa9 Copyright 2011 Cornelius Grimm</p>";

    infos << "<p>This program includes an image io plugin that uses dcraw to extract thumbnail images and meta information from raw images. "
             "dcraw.c -- Dave Coffin's raw photo decoder (<a href=\"http://www.cybercom.net/~dcoffin/dcraw/\">http://www.cybercom.net/~dcoffin/dcraw/</a>). "
             "Copyright 1997-2011 by Dave Coffin, dcoffin a cybercom o net. "
             "This is a command-line ANSI C program to convert raw photos from "
             "any digital camera on any computer running any operating system.</p>";

    infos << "<p>This software uses the library <i>libexif</i> by Lutz Mueller, Jan Patera, Hans Ulrich Niedermann and Hubert Figuiere (<a href=\"http://libexif.sourceforge.net/\">http://libexif.sourceforge.net/</a>). "
             "<i>libexif</i> is licensed under the terms of the GNU Lesser General Public License (LGPL). "
             "The <i>libexif</i> library, its license and source code is bundled with this software package.</p>";
    foreach(PioPlugin * plugin, m_plugins) {
        infos << plugin->licenseInfo();
    }
    AboutDialog d(infos.join(""), this);
    d.setWindowFlags(Qt::SplashScreen);
    d.exec();
}

void MainWindow::onCollectionsListContextMenuRequested(QPoint p)
{
    m_collectionsContextMenu.popup(ui->collectionsList->mapToGlobal(p));
}

void MainWindow::on_actionFullscreen_triggered()
{
    setFullscreen(!isFullScreen());
}

void MainWindow::addOverlay(QWidget *overlay)
{
    ui->imageview->addOverlay(overlay);
    ui->stackedWidget->setCurrentIndex(1);
    ui->imageview->setFocus();
}

void MainWindow::removeOverlay(QWidget *overlay)
{
    ui->imageview->removeOverlay(overlay);
}

void MainWindow::addToolWidget(QWidget *widget, QString title)
{
    ui->toolBox->addItem(widget, title);
}

void MainWindow::removeToolWidget(QWidget *widget)
{
    for(int i = 0; i < ui->toolBox->count(); i++) {
        if(ui->toolBox->widget(i) == widget) {
            ui->toolBox->removeItem(i);
            i--;
        }
    }
}

void MainWindow::selectToolWidget(QWidget *widget)
{
    ui->toolBox->setCurrentWidget(widget);
}

void MainWindow::on_actionCheck_triggered()
{
    QList<MediaItemPtr> sel = m_core.selection();
    bool check = false;
    foreach(MediaItemPtr item, sel)
        if(!item->isChecked())
            check = true;
    foreach(MediaItemPtr item, sel)
        m_core.check(item, check);
}

void MainWindow::on_actionSelectCheckedFiles_triggered()
{
    QList<MediaItemPtr> checked = m_core.checked();
    m_core.select(checked.toSet());
}

void MainWindow::on_actionUncheckAll_triggered()
{
    QList<MediaItemPtr> checked = m_core.checked();
    foreach(MediaItemPtr item, checked)
        m_core.check(item, false);
}

void MainWindow::onKeywordsChanged()
{
    QStringList keywords = m_core.database()->keywords();
    keywords.sort();

    foreach(QString str, keywords) {
        QStringList path = str.split('/');
        QTreeWidgetItem * parent = NULL;
        foreach(QString item, path) {
            parent = addKeyword(item, parent);
        }
    }
}

void MainWindow::onCollectionsChanged()
{
    QSet<QString> unchecked = m_core.filters()->excludedCollections();

    QStringList collections = m_core.database()->collections();
    collections.sort();

    ui->collectionsList->clear();
    ui->collectionsList->addItem(tr("my collection"));
    ui->collectionsList->addItems(collections);
    for(int i=0; i<ui->collectionsList->count(); i++) {
        QListWidgetItem * item = ui->collectionsList->item(i);
        if(i==0) {
            QFont font = item->font();
            font.setBold(true);
            item->setFont(font);
        }
        item->setSizeHint(QSize(32, 32));
        item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
        QString str = (i == 0) ? "" : item->text();
        if(unchecked.contains(str))
            item->setCheckState(Qt::Unchecked);
        else
            item->setCheckState(Qt::Checked);
    }
    selectCollections();
}
